import json
import random
import threading
import logging
import time

from concurrent_log_handler import ConcurrentRotatingFileHandler

import snap7
from snap7.util import get_real, set_real

LOGGER = {
    "LOGGER_NAME": "data_pedestal",
    "TOTAL_LEVEL": logging.INFO,
    "FILE_HANDLER_LEVEL": logging.DEBUG,
    "CONTROL_HANDLER_LEVEL": logging.INFO,
    "FILE_NAME": r"log.txt",
    "MODE": "a",
    "MAX_BYTES": 10 * 1024 * 1024,
    "BACKUP_COUNT": 10,
    "ENCODING": "UTF-8",
    "FORMAT": "%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s"
}


def get_logger() -> logging.getLogger():
    logger = logging.getLogger(LOGGER['LOGGER_NAME'])
    logger.setLevel(LOGGER['TOTAL_LEVEL'])  # 设置日志级别
    file_handler = ConcurrentRotatingFileHandler(filename=LOGGER['FILE_NAME'], mode=LOGGER['MODE'],
                                                 maxBytes=LOGGER['MAX_BYTES'],
                                                 backupCount=LOGGER['BACKUP_COUNT'],
                                                 encoding=LOGGER['ENCODING'])  # 设置输出文件
    file_handler.setLevel(LOGGER['FILE_HANDLER_LEVEL'])
    control_handler = logging.StreamHandler()
    control_handler.setLevel(LOGGER['CONTROL_HANDLER_LEVEL'])
    formatter = logging.Formatter(LOGGER['FORMAT'])
    file_handler.setFormatter(formatter)
    control_handler.setFormatter(formatter)
    logger.addHandler(file_handler)
    logger.addHandler(control_handler)
    return logger


# 创建一个实例
logger = get_logger()

with open('s7_client_config.json', 'r') as f:
    config_txt = f.read()

config = json.loads(config_txt)


class S7Client:
    """
    连接西门子 PLC 的 snap 客户端
    """

    def __init__(self, host: str, port: int, rack: int, slot: int):
        """
        :param host: 地址
        :param port: 端口
        :param rack: 机架号
        :param slot: 插槽号
        """
        self.host = host
        self.port = port
        self.rack = rack
        self.slot = slot
        self._client = snap7.client.Client()  # lib_location=config.DYNAMIC_LIB['SNAP7']
        self._lock = threading.Lock()
        self.connected = False
        self.connect()

    def connect(self):
        """
        和西门子 PLC 建立连接
        """
        # 当其它线程发现已经断线重连成功, 直接 return
        if self.connected:
            return
        # 由于不能重复 connect, 故需先断开一次
        self._client.disconnect()
        while True:
            try:
                self._client.connect(self.host, self.rack, int(self.slot), int(self.port))
                self.connected = True  # 连接成功后, 将状态设置为 True
                return
            except RuntimeError:
                logger.error(
                    f"和 PLC 设备之间的连接建立失败, 请检测设备是否正常, 以及当前机器和 PLC 设备之间的网络是否畅通")
            time.sleep(5)

    def read_tag(self):
        if not self.connected:
            self.connect()

    def read_tags(self):
        if not self.connected:
            self.connect()

    def write_tag(self):
        if not self.connected:
            self.connect()

    def test(self):
        # res = self._client.db_read(1, 0, 600)
        # res = self._client.ab_read(100,100)
        # rs = self._client.read_area(snap7.types.Areas.PA, 0, 0, 32768)  # 32768
        # rs = self._client.read_area(snap7.types.Areas.PE, 0, 0, 32768)  # 32768

        # print(len(rs))
        # print(rs)
        response_bytes: bytearray = self._client.read_area(snap7.types.Areas.DB, 1, 0, 1004)
        g = [i for i in range(0,1000, 4)]
        random.shuffle(g)
        g *= 100
        print(len(g))
        # for dp in config['group1']:
        #     index = dp['dp'].split('.')[1][3:]
        #     res = get_real(response_bytes, int(index))  # use time 0.017218351364135742s
        #     print(res)

        for i in g:
            res = get_real(response_bytes, i)  # use time 0.023069143295288086s  use time 0.018525362014770508s
            #print(res)






if __name__ == '__main__':
    s = time.time()
    c = S7Client('10.3.6.225', 102, 0, 1)
    c.test()
    e = time.time()
    print(f'use time {e-s}s')
